﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
using System.Management;
using System.Net;

namespace ProcessTesting
{
    public partial class ProcessStartWatcherForm : Form
    {
        public ProcessStartWatcherForm()
        {
            InitializeComponent();

            //WebClient wc = new WebClient();
            //byte[] data =
            //    wc.DownloadData("http://www.theinsyde.com");

            WqlEventQuery aProcessCreationQuery = new WqlEventQuery("__InstanceCreationEvent",
                new TimeSpan(0, 0, 1), "TargetInstance isa \"Win32_Process\"");
            //var mgmtWtch = new ManagementEventWatcher("Select * From Win32_ProcessStartTrace");
            ManagementEventWatcher mgmtWtch = new ManagementEventWatcher(aProcessCreationQuery);
            mgmtWtch.EventArrived += new EventArrivedEventHandler(watcher_EventArrived);
            mgmtWtch.Start();
            mgmtWtch.Dispose();
        }

        volatile Process m_Process;
        void watcher_EventArrived(object sender, EventArrivedEventArgs e)
        {
            if (m_Process != null)
                return;

            try
            {
                StringBuilder stringBuilder = new StringBuilder();
                MakePropertyDataString(stringBuilder, e.NewEvent);

                this.Invoke(new Action(() => { textBox1.Text = stringBuilder.ToString(); }));

                {
                    PropertyData targetInstance = e.NewEvent.Properties["TargetInstance"];
                    if (targetInstance != null && targetInstance.Value != null)
                    {
                        using (ManagementBaseObject manBaseObj = targetInstance.Value as ManagementBaseObject)
                        {
                            PropertyData name = manBaseObj.Properties["Name"];
                            PropertyData processId = manBaseObj.Properties["ProcessId"];
                            if (name != null && processId != null)
                            {
                                string strName = name.Value as string;
                                UInt32 nProcessId = (UInt32)processId.Value;
                                if (m_Process == null)
                                {
                                    m_Process = Process.GetProcessById((int)nProcessId);
                                    m_Process.Exited += m_FirstProcess_Exited;
                                    m_Process.EnableRaisingEvents = true;
                                }
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Debug.Assert(false, ex.Message);
            }
        }

        void ReleaseProcess()
        {
            if (m_Process != null)
            {
                this.Invoke(new Action(() => { textBox1.Clear(); }));

                m_Process.Dispose();
                m_Process = null;
            }
        }

        void m_FirstProcess_Exited(object sender, EventArgs e)
        {
            ReleaseProcess();
            bool test = true;
            //throw new NotImplementedException();
        }

        void MakePropertyDataString(StringBuilder stringBuilder, ManagementBaseObject manBaseObject, int offset = 0)
        {
            if (manBaseObject == null)
                return;

            if (stringBuilder == null)
                return;

            foreach (PropertyData data in manBaseObject.Properties)
            {
                stringBuilder.Append(new string('\t', offset) + data.Name);
                if (data.Value != null)
                {
                    stringBuilder.Append(": " + data.Value.ToString());
                }
                stringBuilder.Append(Environment.NewLine);

                if (data.Value != null && data.Value is ManagementBaseObject)
                {
                    MakePropertyDataString(stringBuilder, data.Value as ManagementBaseObject, offset + 1);
                }
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            ReleaseProcess();
        }
    }
}
